# plot_window.py
from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QGroupBox, QPushButton, QComboBox,
                             QGridLayout, QLabel, QDoubleSpinBox, QCheckBox, QHBoxLayout)
from PyQt6.QtCore import pyqtSlot, pyqtSignal, Qt
import pyqtgraph as pg
from collections import deque
import struct  # 需要导入struct来打包写入命令


class PlotWindow(QWidget):
    # 定义信号，用于请求主窗口发送指令
    send_command_requested = pyqtSignal(bytes)
    window_closed = pyqtSignal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowFlags(self.windowFlags() | Qt.WindowType.Window)
        self.setWindowTitle("数据采集与绘图")
        self.setGeometry(200, 200, 800, 700)

        # 绘图相关数据结构
        self.plot_data_buffers = {}
        self.plot_curves = {}
        self.channel_colors = ['b', 'r', 'g', 'c', 'm', 'y', 'k']

        self._init_ui()

    def _init_ui(self):
        main_layout = QVBoxLayout(self)

        # --- 将数据采集配置面板移到这里 ---
        acq_groupbox = QGroupBox("数据采集配置")
        acq_layout = QGridLayout()
        acq_groupbox.setLayout(acq_layout)

        plot_sources = ["源0", "源1", "源2", "源3", "源4", "源5", "源6", "源7", "源8", "源9", "源10", "源11", "源12", "源13", "源14", "源15",
                        "源f0", "源f1", "源f2", "源f3", "源f4", "源f5", "源f6", "源f7", "源f8", "源f9", "源f10", "源f11", "源f12", "源f13", "源f14", "源f15"]
        trigger_modes = ["无触发", "上升沿", "下降沿"]
        trigger_sources = ["源0", "源1", "源2", "源3"]

        acq_layout.addWidget(QLabel("绘图通道1源:"), 0, 0)
        self.combo_plot1 = QComboBox()
        self.combo_plot1.addItems(plot_sources)
        acq_layout.addWidget(self.combo_plot1, 0, 1)
        acq_layout.addWidget(QLabel("采样频率 (Hz):"), 0, 2)
        self.spin_freq = QDoubleSpinBox()
        self.spin_freq.setRange(1.0, 100000.0)
        self.spin_freq.setValue(5000.0)
        acq_layout.addWidget(self.spin_freq, 0, 3)
        acq_layout.addWidget(QLabel("绘图通道2源:"), 1, 0)
        self.combo_plot2 = QComboBox()
        self.combo_plot2.addItems(plot_sources)
        acq_layout.addWidget(self.combo_plot2, 1, 1)
        acq_layout.addWidget(QLabel("触发模式:"), 1, 2)
        self.combo_trigger_mode = QComboBox()
        self.combo_trigger_mode.addItems(trigger_modes)
        acq_layout.addWidget(self.combo_trigger_mode, 1, 3)
        acq_layout.addWidget(QLabel("绘图通道3源:"), 2, 0)
        self.combo_plot3 = QComboBox()
        self.combo_plot3.addItems(plot_sources)
        acq_layout.addWidget(self.combo_plot3, 2, 1)
        acq_layout.addWidget(QLabel("触发源:"), 2, 2)
        self.combo_trigger_source = QComboBox()
        self.combo_trigger_source.addItems(trigger_sources)
        acq_layout.addWidget(self.combo_trigger_source, 2, 3)
        self.check_autosend = QCheckBox("自动回传数据")
        self.check_autosend.setChecked(True)
        acq_layout.addWidget(self.check_autosend, 3, 0)
        acq_layout.addWidget(QLabel("触发阈值/长度:"), 3, 2)
        self.spin_trigger_len = QDoubleSpinBox()
        self.spin_trigger_len.setRange(0, 65535.0)
        self.spin_trigger_len.setValue(100.0)
        acq_layout.addWidget(self.spin_trigger_len, 3, 3)

        # 将按钮连接到发射信号的槽函数
        acq_buttons_layout = QHBoxLayout()
        acq_buttons_layout.addWidget(QPushButton("读取配置", clicked=self._on_read_config_clicked))
        acq_buttons_layout.addWidget(QPushButton("写入配置", clicked=self._on_write_config_clicked))
        acq_layout.addLayout(acq_buttons_layout, 4, 0, 1, 2)

        start_stop_layout = QHBoxLayout()
        start_stop_layout.addWidget(QPushButton("开始采集", clicked=lambda: self.send_command_requested.emit(b'fes1'), styleSheet="background-color: lightgreen"))
        start_stop_layout.addWidget(QPushButton("停止采集", clicked=lambda: self.send_command_requested.emit(b'fes0'), styleSheet="background-color: lightcoral"))
        acq_layout.addLayout(start_stop_layout, 4, 2, 1, 2)

        main_layout.addWidget(acq_groupbox)

        # --- 绘图区域 ---
        plot_groupbox = QGroupBox("实时曲线图")
        plot_layout = QVBoxLayout()
        plot_groupbox.setLayout(plot_layout)
        self.plot_widget = pg.PlotWidget()
        self.plot_widget.setBackground('w')
        self.plot_widget.showGrid(x=True, y=True)
        self.plot_widget.setLabel('left', '幅值')
        self.plot_widget.setLabel('bottom', '数据点')
        self.plot_widget.addLegend()
        plot_layout.addWidget(self.plot_widget)
        main_layout.addWidget(plot_groupbox, 1)

    def _on_read_config_clicked(self):
        self.send_command_requested.emit(b'far')

    def _on_write_config_clicked(self):
        try:
            payload = bytearray(b'fas')
            payload.append(self.combo_plot1.currentIndex())
            payload.append(self.combo_plot2.currentIndex())
            payload.append(self.combo_plot3.currentIndex())
            payload.append(self.combo_trigger_mode.currentIndex())
            payload.append(self.combo_trigger_source.currentIndex())
            payload.append(1 if self.check_autosend.isChecked() else 0)
            period = 1.0 / self.spin_freq.value() if self.spin_freq.value() != 0 else 0
            payload.extend(struct.pack('<f', period))
            trigger_len = self.spin_trigger_len.value()
            payload.extend(struct.pack('<f', float(trigger_len)))
            self.send_command_requested.emit(bytes(payload))
        except Exception as e:
            print(f"构建写入配置命令失败: {e}")  # 可以在此发射错误信号

    # --- 槽函数，用于接收数据并更新UI ---
    @pyqtSlot(dict)
    def update_plot_data(self, plot_data_dict: dict):
        channel_index = plot_data_dict.get('channel')
        new_points = plot_data_dict.get('data', [])
        if channel_index is None or not new_points: return
        if channel_index not in self.plot_curves:
            self.plot_data_buffers[channel_index] = deque(maxlen=2000)
            color = self.channel_colors[channel_index % len(self.channel_colors)]
            curve = self.plot_widget.plot(pen=pg.mkPen(color, width=2), name=f"通道 {channel_index}")
            self.plot_curves[channel_index] = curve
        self.plot_data_buffers[channel_index].extend(new_points)
        self.plot_curves[channel_index].setData(list(self.plot_data_buffers[channel_index]))

    @pyqtSlot(dict)
    def update_acq_config_ui(self, data: dict):
        """根据从主窗口接收的数据更新配置UI"""
        self.combo_plot1.setCurrentIndex(data.get('p1', 0))
        self.combo_plot2.setCurrentIndex(data.get('p2', 0))
        self.combo_plot3.setCurrentIndex(data.get('p3', 0))
        self.combo_trigger_mode.setCurrentIndex(data.get('t_mode', 0))
        self.combo_trigger_source.setCurrentIndex(data.get('t_src', 0))
        self.spin_freq.setValue(data.get('freq', 1000.0))
        self.check_autosend.setChecked(data.get('autosend', False))
        self.spin_trigger_len.setValue(data.get('t_len', 0.0))

    def reset(self):
        self.plot_widget.clear()
        self.plot_data_buffers.clear()
        self.plot_curves.clear()
        self.plot_widget.addLegend()

    def closeEvent(self, event):
        self.hide()
        self.window_closed.emit()
        event.ignore()